今天我們要來利用模組化後的Vue來進行一些操作。
而組件的基本架構如下:
<template>
模板
<h1 class="title"> {{ ... }}</h1>
</template>
<script>
程式
export default {
name:"titleData",
}
</script>
<style>
樣式
</style>
首先我們想要創建一個能夠顯示Title的組件。
第一步就是要在App.vue中先引入他。
// 要將component渲染到畫面上,首先要import進App.vue
import Title from './components/Title.vue'
接著掛載在我們的components
components: {
HelloWorld,
Title,
},
最後將引入的組件加至template中。
<template>
<div id="app">
<Title titleData="hello jojo"/>
<HelloWorld msg="Welcome to Your Vue.js App" />
</div>
</template>
而我們在Title的組件中也要做一些處理。
模板的部分:
<template>
<h1 class="title"> {{ titleData }}</h1>
</template>
程式的部分:data部分要用func型式
,而不是物件(include作法),因為component會共用
,如果直接做物件出來,每個component都會包到同一包資料,也就是會互相影響。
<script>
export default {
name:"titleData",
data() {
return {
title:"hello jojo"
}
},
<script>
而每一個組件都是獨立的,我們無法直接從子組件獲取父組件的資料
,而我們現在只想要這個模組顯示資料
,而不用包含資料
,也就是說資料是從父層傳過來
,就要透過Props,而Props是單向的,只會從父層傳至子層,Props 的值也會因父層改變而改變。
<script>
export default {
name:"titleData",
// data() {
// return {
// title:"hello jojo"
// }
// },
// 接收從外部(App.vue的 <Title/>)傳進來的資料titleData="hello jojo"
// 記得template中的資料也要改成titleData
props:{
// 給我一個titleData
titleData:{
// 類型是字串
type:String,
// required就是一定要
required:true
}
}
}
</script>
樣式的部分:
為了不影響到其他組件
,我們可以使用scoped,scoped可以將樣式封裝在當前模組
,盡量不要直接搭配tag,要加上class,id,否則效能會較差,如果不加上scoped就會影響到其他component。
<style scoped>
h1.title {
color:#fa5
}
</style>
加上scoped前(上圖),加上後(下圖)。
而在App.vue的部分,我們除了可以直接傳遞資料外。
<template>
// 利用直接傳遞資料的方法
<Title titleData="hello jojo"/>
</template>
也可以利用綁定的方式來傳遞我們的資料,記得要將我們所要綁定的資料,在data函數中將值設置進去。
<template>
// 利用資料綁定的方法傳遞資料
<Title :titleData="bindData"/>
</template>
export default {
name: 'App',
data() {
return {
bindData:"this is a bind msg"
}
},
除此之外,我們這邊再做一個input的組件,且當輸入框改變,畫面的資料也會同步跟著改變,而這個組件我們先創建一個資料夾,並分別創建template,vue,css。
然後在父組件,按照創建組件的流程,引入組件、掛載組件、最後在套用組件。
將資料(bindData)傳入至子組件。
<InputComponent :text="bindData"/>
而在子組件我們利用props接收父組件傳入的資料。
export default {
name:"input-component",
// 獲取的屬性及值
props:{
text:{
type:String,
required:true
}
}
}
template部分
<input
type="text"
v-model="text"
>
而後當我們改變input的值,會發現報錯,因為直接從子組件改變外部資料是不允許的,也就是說我們不能更動原資料
(App.vue父層),因此我們寫一個computed來改變子層資料,並同步更新父層資料
。
computed的屬性可以被視為像是 data 一樣,可以讀取和設值,因此在computed中分成getter(讀取)
和setter(設值)
,在沒有寫 setter 的情況下,computed 預設為 getter
,也就是只能讀取,不能改變設值
,getter
在大部分的時候是當內部觀察的資料有改變時會被觸發
;setter 則是當被觀察的物件本身有改變時會被觸發
,也就是當我們改變輸入框的值時。
而在setter部分,可透過emit將子組件的資料傳遞至父組件
,這邊我們傳遞一個事件textChange,並傳遞一個value
(子組件input當前的值)。
computed: {
inputText:{
// 獲取值
get(){
console.log("get");
return this.text
},
// 設置值
set(value){
console.log(value)
// 子組件與父組件溝通的橋樑
// this.$emit('event', […args])
this.$emit('textChange', value)
}
}
},
記得在template將綁定從 v-model="text" 改成inputText也就是我們包含兩個函數的 computed。
<input
type="text"
v-model="inputText"
>
子組件設置完成後,我們再回到父組件,接收從子層傳來的事件,並加上一個函數處理傳來的值。
<InputComponent :text="bindData" @textChange="changeHandler" />
methods中處理子組件傳來的值,將其同步到父組件的資料。
methods: {
// 處理子層傳來的值(input中的值)
changeHandler(value){
// 將input中的值同步改變 bindData中的值
this.bindData = value
}
},
而我們打開Vue Devtools,可發現我們的子組件本身都沒有資料,那資料在哪裡呢?都統一放在我們的父組件做管理,分給其他子組件使用,所以當我們在子組件改變輸入框的值,他會呼叫外部的資料,也就是父層的資料也進行改變,而父層的資料又會同步更新到畫面上。